package com.itjeffrey.autocode.util;

import com.alibaba.fastjson.JSON;
import com.itjeffrey.autocode.enums.OrderEnum;
import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据结构工具类
 * 各种数据结构的用法，案例...
 * @From: Jeffrey
 * @Date: 2021/4/19
 */
public class DataStructrueUtils {

    private static Logger logger = LoggerFactory.getLogger(DataStructrueUtils.class);

    /**
     * Apache Commons Collection4 包下的提供双向Map的接口BidiMap，支持一对一映射关系，不能多对一
     *  通过bidiMap.getKey(obj)方法获取对应的key值
     *  与Guava的BiMap不同的是，当put相同value时不会抛异常，会覆盖原来的数据
     */
    public static void testBidiMap(){
        BidiMap<String, Integer> bidiMap = new DualHashBidiMap<>();
        bidiMap.put("1", 23);
        bidiMap.put("2", 22);
        bidiMap.put("3", 21);
        bidiMap.put("4", 21);
        System.err.println(JSON.toJSONString(bidiMap));
    }

    /**
     * Map按key进行升序排序
     */
    public static Map<Integer, String> sortMapByKey(Map<Integer, String> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<Integer, String> sortMap = new TreeMap<Integer, String>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        sortMap.putAll(map);
        return sortMap;
    }

    /**
     * map根据key排序
     * @param map
     * @return
     */
    public static Map<String, Object> sortMapByKey(Map<String, Object> map, OrderEnum orderEnum){
        Objects.requireNonNull(map, "map require non null");
        return orderEnum.equals(OrderEnum.ASC) ?
                map.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue, (key1, key2) -> key1, LinkedHashMap::new)) :
                map.entrySet().stream().sorted(Map.Entry.<String, Object>comparingByKey().reversed()).collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue, (key1, key2) -> key1, LinkedHashMap::new));
    }

    /**
     * map根据key升序
     * @param map
     * @return
     */
    public static Map<String, Object> sortMapByKeyASC(Map<String, Object> map){
        Objects.requireNonNull(map, "map require non null");
        return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(Collectors.toMap(Map.Entry::getKey,
                        Map.Entry::getValue, (key1, key2) -> key1, LinkedHashMap::new));
    }

    /**
     * map根据key降序
     * @param map
     * @return
     */
    public static Map<String, Object> sortMapByKeyDESC(Map<String, Object> map){
        Objects.requireNonNull(map, "map require non null");
        return map.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.reverseOrder())).collect(Collectors.toMap(Map.Entry::getKey,
                Map.Entry::getValue, (key1, key2) -> key1, LinkedHashMap::new));
    }

    /**
     * map根据key排序，不推荐
     * @param map
     * @return
     */
    public static Map<String, Object> sortMap2(Map<String, Object> map){
        Objects.requireNonNull(map, "map require non null");
        Map<String, Object> newMap = new LinkedHashMap<>();
        map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(entry -> newMap.put(entry.getKey(),
                entry.getValue()));
        return newMap;
    }

}
